/**
  ******************************************************************************
  * @file    delay_no_block.c
  * @author  ashuai0110
  * @version V2.1
  * @date    2023-09-24
  * @brief   非阻塞延时
  *
  ******************************************************************************
  * @attention
  *
  * 版权声明:内容为编者(ashuai0110)原创,使用请注明出处,当然,你也可以不这样做^_^
  * 出处链接:https://gitee.com/ashuai0110/mcu_reuse_development_module.git
  *
  ******************************************************************************
  */

/* 包含头文件-----------------------------------------------------------------*/
#include "delay_no_block.h"

/**
 * @addtogroup modules
 * @{
 */

/**
 * @defgroup delay_no_block delay_no_block
 * @{
 */

/* 私有宏定义-----------------------------------------------------------------*/
/**
 * @defgroup delay_no_block_local_macros delay no block local macros
 * @{
 */

#define DELAY_TICKS_MAX             (0x7FFFFFFFul) /* 最大计数值(默认不改) */

/**
 * @defgroup delay_no_block_check_parameters_validity delay no block check parameters validity
 * @{
 */
/* 延时任务ID有效性检查 */
#define IS_VALID_DELAY_ID(x)                                                  \
(   ((x) == 0)                             ||                                 \
    (((x) > 0)                             &&                                 \
    ((x) <= DELAY_TASK_SIZE)))

/* 延时任务计数值有效性检查 */
#define IS_VALID_DELAY_TICKS(x)                                               \
(   ((x) >= 1)                             &&                                 \
    ((x) <= DELAY_TICKS_MAX))
/**
 * @}
 */

/**
 * @}
 */

/* 私有类型定义---------------------------------------------------------------*/

/* 私有变量-------------------------------------------------------------------*/
/**
 * @defgroup delay_no_block_local_variables delay no block local variables
 * @{
 */

static delay_item_t delayTaskArr[DELAY_TASK_SIZE]; /* 延时任务工作数组 */
volatile static uint32_t delayBaseTicks;             /* 基本计数值 */

/**
 * @}
 */

/* 全局变量-------------------------------------------------------------------*/

/* 私有函数原型---------------------------------------------------------------*/

/**
 * @defgroup delay_no_block_global_functions delay no block global functions
 * @{
 */

/**
  * @brief  创建延时任务
  *
  * @param  _id        : 延时任务ID  首次调用为新建,之后为更新参数
  *
  * @param  delayTicks : 延时任务计数值  例如延时500ms,轮询周期10ms,则delayTicks=500ms/10ms=50
  *
  * @retval uint8_t
  *    @arg RET_OK     : 创建成功
  *    @arg RET_ERR    : 任务已满(创建失败)
  */
uint8_t delay_init(delay_id_t *_id, uint32_t delayTicks)
{
    delay_id_t idCnt;
    
    ASSERT_PARAM(IS_VALID_POINT(_id));
    ASSERT_PARAM(IS_VALID_DELAY_ID(*_id));
    ASSERT_PARAM(IS_VALID_DELAY_TICKS(delayTicks));
    
    if(0 == *_id)
    {
        for(idCnt = 0; idCnt < DELAY_TASK_SIZE; idCnt++)
        {
            if(0 == delayTaskArr[idCnt].ticks && 0 == delayTaskArr[idCnt].run)
            {
                delayTaskArr[idCnt].ticks = delayBaseTicks + delayTicks;
                delayTaskArr[idCnt].run = 1;
                *_id = idCnt + 1;
                
                break;
            }
        }
    }
    else
    {
        delayTaskArr[*_id - 1].ticks = delayBaseTicks + delayTicks;
        delayTaskArr[*_id - 1].run = 1;
    }
    
    return *_id ? RET_OK : RET_ERR;
}

/**
  * @brief  延时任务取消初始化
  *
  * @param  _id : 延时任务ID
  *
  * @retval None
  */
void delay_de_init(delay_id_t *_id)
{
    ASSERT_PARAM(IS_VALID_POINT(_id));
    ASSERT_PARAM(IS_VALID_DELAY_ID(*_id));
    
    memset(&delayTaskArr[*_id - 1], 0, sizeof(delay_item_t));
    *_id = 0;
}

/**
  * @brief  等待延时任务返回完成
  *
  * @param  _id     : 延时任务ID
  *
  * @retval uint8_t
  *    @arg RET_OK  : 延时完成
  *    @arg RET_ERR : 无延时任务
  *    @arg RET_ING : 延时进行中
  */
uint8_t delay_wait(delay_id_t *_id)
{
    ASSERT_PARAM(IS_VALID_POINT(_id));
    ASSERT_PARAM(IS_VALID_DELAY_ID(*_id));
    
    if(0 == delayTaskArr[*_id - 1].ticks || 0 == delayTaskArr[*_id - 1].run)
    {
        return RET_ERR;
    }
    
    if(delayBaseTicks > delayTaskArr[*_id - 1].ticks)
    {
        delayTaskArr[*_id - 1].ticks = 0;
        
        return RET_OK;
    }
    
    return RET_ING;
}

/**
  * @brief  延时任务轮询处理
  *
  * @note   此函数执行周期即是延时任务计数值累加周期
  *
  * @param  None
  *
  * @retval None
  */
void delay_poll(void)
{
    delayBaseTicks++;
    
    if(DELAY_TICKS_MAX < delayBaseTicks)
    {
        delayBaseTicks = 0;
        
        delay_id_t idCnt;
        
        for(idCnt = 0; idCnt < DELAY_TASK_SIZE; idCnt++)
        {
            if(DELAY_TICKS_MAX < delayTaskArr[idCnt].ticks)
            {
                delayTaskArr[idCnt].ticks = delayTaskArr[idCnt].ticks - DELAY_TICKS_MAX;
            }
        }
    }
}

/**
  * @brief  读取基本计数值
  *
  * @param  None
  *
  * @retval 基本计数值
  */
uint32_t delay_ticks(void)
{
    return delayBaseTicks;
}

/**
 * @}
 */

/**
 * @}
 */

/**
 * @}
 */
